/*
 * Resolve.c
 *
 *  Created on: 2011-7-22
 *      Author: gexiao
 */

/*
 * Resolve classes, methods, fields, and strings.
 *
 * According to the VM spec (v2 5.5), classes may be initialized by use
 * of the "new","getstatic","putstatic",or "invokestatic" instructions.
 * If we are resolving a static method or static field, we make the
 * initialization check here.
 *
 * (NOTE: the verifier has its own resolve functions,which can be invoked
 * if a class isn't pre-verified. Those functions must not update the
 * "resolved stuff" tables for static fields and methods, because they do
 * not perform initialization.)
 */
#include "../Dalvik.h"

#include <stdlib.h>

/*
 * Find the class corresponding to "classIdx", which maps to a class name
 * string. It might be in the same DEX file as "referrer", in a different
 * DEX file, generated by a class loader, or generated by the VM (e.g.
 * array classes).
 *
 * Because the DexTypeId is associated with the referring class' DEX file,
 * we may have to resolve the same class more than once if it's referred
 * to from class in multiple DEX files. This is a necessary property for
 * DEX files associated with different class loaders.
 *
 * We cache a copy of the lookup in the DexFile's "resolved class" table,
 * so future references to "classIdx" are faster.
 *
 * Note that "referrer" may be in the process of being linked.
 *
 * Traditional VMs might do access checks here, but in Dalvik the class
 * "constant pool" is shared between all classes in the DEX file. We rely
 * on the verifier to do the checks for us.
 *
 * Does not initialize the class.
 *
 * "from UnverifiedConstant" should only be set if this call is the direct
 * result of executing a "const-class" or "instance-of" instruction, which
 * use class constants not resolved by the bytecode verifier.
 *
 * Returns NULL with an exception raised on failure.
 */
ClassObject* dvmResolveClass(const ClassObject* referrer, u4 classIdx,
		bool fromUnverifiedConstant) {
	DvmDex* pDvmDex = referrer->pDvmDex;
	ClassObject* resClass;

	/*
	 * Check the table first -- this gets called from the other "resolve"
	 * methods.
	 */
	resClass = dvmDexGetResolvedClass(pDvmDex, classIdx);
	if (resClass != NULL)
		return resClass;

	/*
	 * Class hasn't been loaded yet, or is in the process of being loaded
	 * and initialized now. Try to get a copy. If we find one, put the
	 * pointer in the DexTypeId. There isn't a race condition here --
	 * 32-bit writes are guaranteed atomic on all target platforms. Worst
	 * case we have two threads storing the same value.
	 *
	 * If this is an array class, we'll generate it here.
	 */
	resClass = dvmFindClassNoInit(
			dexStringByTypeIdx(pDvmDex->pDexFile, classIdx),
			referrer->classLoader);

	if (resClass != NULL) {
		/*
		 * If the referrer was pre-verified, the resolved class must come
		 * from the same DEX or from a bootstrap class. The pre-verifier
		 * makes assumptions that could be invalidated by a wacky class
		 * loader. (See the notes at the top of oo/Class.c.)
		 *
		 * The verifier does *not* fail a class for using a const-class
		 * or instance-of instruction referring to an unresolveable class,
		 * because the result of the instruction is simply a Class Object
		 * or boolean -- there's no need to ...
		 */
		if (!fromUnverifiedConstant
				&&IS_CLASS_FLAG_SET(referrer,CLASS_ISPREVERIFIED)) {
			ClassObject* resClassCheck = resClass;
			if (dvmIsArrayClass(resClassCheck))
				resClassCheck = resClassCheck->elementClass;

			if (referrer->pDvmDex != resClassCheck->pDvmDex
					&& resClassCheck->classLoader != NULL) {
				dvmThrowException("Ljava/lang/IllegalAccessError;",
						"cross-loader access from pre-verified class");
				return NULL;
			}
		}

		/*
		 * Add what we found to the list so we can skip the class search
		 * next time through.
		 *
		 * TODO: should we be doing this when fromUnverifiedConstant==true?
		 * (see comments at top of oo/Class.c)
		 */
		dvmDexSetResolvedClass(pDvmDex, classIdx, resClass);
	} else {
		//not found, exception should be raised
		assert(dvmCheckException(dvmThreadSelf()));
	}
	return resClass;
}

/*
 *
 */
Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx,
		MethodType methodType) {

}

/*
 *
 */
Method* dvmResolveInterfaceMethod(const ClassObject* referrer, u4 methodIdx) {

}

/*
 *
 */
InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx) {

}

/*
 *
 */
StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx) {

}

/*
 *
 */
StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx) {

}
